package com.demo.core.service.base.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.security.authentication.encoding.PasswordEncoder;

import com.demo.common.StringUtils;
import com.demo.core.dao.UserDao;
import com.demo.core.dao.base.support.ResultSearchResult;
import com.demo.core.dao.base.support.SearchArgumentSupport;
import com.demo.core.model.User;
import com.demo.core.service.base.UserService;
import com.demo.core.service.exception.UserAlreadyExistedException;
import com.demo.core.service.exception.UserNotFoundOrPasswordErrorException;

/**
 * 用户服务实现类
 * <p>1.对密码进行验证和重置操作将依赖SpringSecurity的PasswordEncoder接口</p>
 * 
 * @author ryuu.kk
 */
public class UserServiceImpl implements UserService, BeanFactoryAware {
	
	/**
	 * 密码编码对象
	 */
	private PasswordEncoder passwordEncoder;
	
	/**
	 * 用户接口Dao
	 */
	private UserDao userDao;
	
	@Override
	public Long save(User user) throws UserAlreadyExistedException {
		//DataAccessException
		String userName = user.getUserName();
		Map<String, Object> params = new HashMap<String, Object>(3);
		params.put("userName", userName);
		List<?> userList = userDao.select(params);
		if (userList.size() > 0) {
			// 用户已经存在
			UserAlreadyExistedException e = new UserAlreadyExistedException(user, "user had already existed.");
			e.setI18n("user.already.existed");
			throw e;
		}
		return userDao.insert(user);
	}
	
	@Override
	public void delete(Long userId) {
		userDao.delete(userId);
	}
	
	@Override
	public boolean exists(Long id) {
		return userDao.exists(id);
	}
	
	@Override
	public boolean exists(String userName) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userName", userName);
		List<User> userList = userDao.select(params);
		return (userList != null && userList.size() > 0);
	}
	@Override
	public void expireDay(Long id, Date expireDay) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		User user = new User();
		user.setExpireDay(expireDay);
		params.put("id", id);
		userDao.updateStatus(user, params);
	}
	
	@Override
	public void enable(Long id, boolean enabled) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		User user = new User();
		user.setEnabled(enabled);
		params.put("id", id);
		userDao.updateStatus(user, params);
	}

	@Override
	public void lock(Long id, boolean locked) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		User user = new User();
		user.setLocked(locked);
		params.put("id", id);
		userDao.updateStatus(user, params);
	}

	@Override
	public void isValid(Long id, boolean isValid) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		User user = new User();
		user.setIsValid(isValid);
		params.put("id", id);
		userDao.updateStatus(user, params);
	}
	
	@Override
	public void resetPassword(Long userId, String newpassword) throws UserNotFoundOrPasswordErrorException {
		User user = this.find(userId);
		if (user == null) {
			throw new UserNotFoundOrPasswordErrorException(userId, "User(id=" + userId + ") not found or password is invalid.");
		}
		if (passwordEncoder == null){
			throw new RuntimeException("not found PasswordEncoder in Spring BeanFactory");
		}
		Map<String, Object> params = new HashMap<String, Object>(3);
		params.put("id", userId);
		String newPass = passwordEncoder.encodePassword(newpassword, user.getSalt());
		// 重置密码
		userDao.resetPassword(newPass, params);
	}
	
	@Override
	public void resetPassword(Long userId, String oldpassword, String newpassword) throws UserNotFoundOrPasswordErrorException {
		User user = this.find(userId);
		if (user == null) {
			throw new UserNotFoundOrPasswordErrorException(userId, "User(id=" + userId + ") not found or password is invalid.");
		}
		if (passwordEncoder == null){
			throw new RuntimeException("not found PasswordEncoder in Spring BeanFactory");
		}
		if (passwordEncoder.isPasswordValid(user.getPassword(), oldpassword, user.getSalt())) {
			Map<String, Object> params = new HashMap<String, Object>(3);
			params.put("id", userId);
			String newPass = passwordEncoder.encodePassword(newpassword, user.getSalt());
			// 重置密码
			userDao.resetPassword(newPass, params);
		}
	}
	
	@Override
	public void resetPassword(String userName, String oldpassword, String newpassword) throws UserNotFoundOrPasswordErrorException {
		User user = this.find(userName);
		if (user == null) {
			throw new UserNotFoundOrPasswordErrorException(userName, "User(UserName=" + userName + ") not found or password is invalid.");
		}
		//PasswordEncoder passwordExcoder = beanFactory.getBean(org.springframework.security.authentication.encoding.PasswordEncoder.class);
		if (passwordEncoder != null && passwordEncoder.isPasswordValid(user.getPassword(), oldpassword, user.getSalt())) {
			Map<String, Object> params = new HashMap<String, Object>(3);
			params.put("id", user.getId());
			String newPass = passwordEncoder.encodePassword(newpassword, user.getSalt());
			// 重置密码
			userDao.resetPassword(newPass, params);
		} else {
			throw new RuntimeException("not found PasswordEncoder in Spring BeanFactory");
		}
	}
		
	
	@Override
	public void update(Long id, User user) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", id);
		userDao.update(user, params);
	}
	
	@Override
	public User find(String userName) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		params.put("userName", userName);
		List<User> userList = userDao.select(params);
		return userList.size() == 1 ? userList.get(0) : null;
	}

	@Override
	public User find(Long id) {
		return userDao.select(id);
	}
	
	@Override
	public User _find(String p) {
		if (StringUtils.isEmpty(p)) {
			return null;
		}
		User u = find(p);
		if (u != null) {
			// 清除密码 for 安全
			u.setPassword("");
		}
		return u;
	};
	
	@Override
	public ResultSearchResult<User> search(String orderBy, int firstResult, int maxResults) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		params.put("orderBy", orderBy);
		SearchArgumentSupport args = new SearchArgumentSupport(firstResult, maxResults);
		return userDao.search(params, args);
	}
	
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	
	@Override
	public ResultSearchResult<User> search(SearchArgumentSupport args) {
		Map<String, Object> params = new HashMap<String, Object>(2);
		return userDao.search(params, args);
	}

	/**
	 * 设置密码编码对象
	 * @param passwordEncoder PasswordEncoder
	 */
	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
		this.passwordEncoder = passwordEncoder;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		if (passwordEncoder == null) {
			this.passwordEncoder = beanFactory.getBean(org.springframework.security.authentication.encoding.PasswordEncoder.class);
		}	
	}
}
